package org.cjprods.icerupt;

import java.io.IOException;
import java.lang.invoke.ConstantCallSite;
import java.nio.FloatBuffer;
import java.nio.channels.Pipe;
import java.util.HashMap;

import com.hackoeur.jglm.Mat3;
import com.hackoeur.jglm.Mat4;
import com.hackoeur.jglm.Matrices;
import com.hackoeur.jglm.Vec;
import com.hackoeur.jglm.Vec3;
import com.hackoeur.jglm.Vec4;

import org.lwjgl.BufferUtils;
import org.lwjgl.system.MathUtil;

import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL12.*;
import static org.lwjgl.opengl.GL13.*;
import static org.lwjgl.opengl.GL14.*;
import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL20.*;
import static org.lwjgl.opengl.GL21.*;
import static org.lwjgl.opengl.GL30.*;
import static org.lwjgl.opengl.GL31.*;
import static org.lwjgl.opengl.GL32.*;
import static org.lwjgl.opengl.GL33.*;


public class camera
{
	Vec3 rotation;
	Vec3 position;
	Vec3 distance;
	Mat3 m;
	Vec3 eye_;
	static float tank_size = 0.25f;

	public void dist(Vec3 d) { distance = d; }
	public Vec3 eye() { return eye_; }
	public Vec3 pos() { return position; }
	public Mat3 get() { return m; }
	
	public camera()
	{
		reset();
	}
	
	public void reset()
	{
		rotation = new Vec3();
		position = new Vec3(0, -2 + tank_size, 3);
		distance = new Vec3(0,  0.5f, 2);
	}
	
	public void xmove(float speed)
	{
		Vec3 o = m.multiply(new Vec3(1.0f, 0.0f, 0.0f));
		o = new Vec3(o.getX(), 0, o.getZ());
		o = o.getUnitVector().scale(speed);
		position = position.add(o);
	}

	public void ymove(float speed)
	{
		position = new Vec3(position.getX(), position.getY() + speed, position.getZ());
	}

	public void zmove(float speed)
	{	
		Vec3 o = m.multiply(new Vec3(0.0f, 0.0f, 1.0f));
		o = new Vec3(o.getX(), 0, o.getZ());
		o = o.getUnitVector().scale(speed);
		position = position.add(o);
	}
	
	public void rotate(Vec3 offset)
	{
		rotation = rotation.add(offset);
		float pi = 3.141592654f;
		float rad89 = pi * 89.0f / 180.0f;
		float rad39 = pi * 39.0f / 180.0f;
		rotation = new Vec3(utils.clamp(rotation.getX(), -rad89, rad39),
				rotation.getY(), rotation.getZ());
	}
	
	public void update()
	{	
		if (position.getZ() < 3.5) position = new Vec3(position.getX(), position.getY(), 3.5f);
		if (position.getZ() > 150) position = new Vec3(position.getX(), position.getY(), 150);
		
		Mat4 mz = Matrices.rotate(rotation.getY(), new Vec3(0.0f, 1.0f, 0.0f))
					.multiply(Matrices.rotate(rotation.getX(), new Vec3(1.0f, 0.0f, 0.0f)));
		//			.multiply(new Vec4(0.0f, 0.0f, 1.0f, 0.0f));
		
		Vec3 zz = utils.reduce_dimension(mz).multiply(new Vec3(0.0f, 0.0f, 1.0f));

		Vec3 z = new Vec3(zz.getX(), zz.getY(), zz.getZ()); 
		Vec3 y = new Vec3(0.0f, 1.0f, 0.0f);
		Vec3 x = y.cross(z).getUnitVector();
		y = z.cross(x);
		m = new Mat3(x, y, z);
		
		float occluder = -2 + 0.1f;
		Vec3 o = m.multiply(distance);
		
		if (position.getY() + o.getY() < occluder)
			o = o.scale((position.getY()-occluder) / -o.getY());
		
			
		eye_ = position.add(o);
	}

}
